#include <stdio.h>
#include <cmath>
#include <vector>

#include "functions.hpp"

using namespace std;

#define PI	3.14

/* -30 <= xi <= 30 dla i = 1...n */
double ackley(vector<double> x)
{
	int i, n = x.size();
	double n_ = (double)1/n;
	double sum1 = 0.0;
	double sum2 = 0.0;
	
	for ( i = 0; i < n; i++ )
	{
		sum1 += pow(x[i],2);
		sum2 += cos(2*PI*x[i]);
	}

	double fx = -20.0*exp(-0.2*sqrt(n_)*sum1) - exp(n_*sum2);
	return fx;
}

double geem(double x1, double x2)
{
	double fx = 4.0*pow(x1,2) - 2.1*pow(x1,4) + (1.0/3.0)*pow(x1,6) + x1*x2 - 4.0*pow(x2,2) + 4.0*(x2,4);
	return fx;
}

double goldstein_price(double x1, double x2)
{
	double fx = (1.0 + pow(x1+x2+1.0,2)*(19.0 - 14.0*x1 + 3.0*pow(x1,2) - 14.0*x2 + 6.0*x1*x2 + 3.0*pow(x2,2)))
		*(30.0 + pow(2.0*x1-3.0*x2,2)*(18.0 - 32.0*x1 + 12.0*pow(x1,2)+48.0*x2-36.0*x1*x2+27.0*pow(x2,2)));
	return fx;
}

/* x c [-5, 5] */
double himmelblau(double x1, double x2)
{
	double fx = pow(pow(x1,2)+x2-11.0,2) + pow(x1+pow(x2,2)-7.0,2) - 200.0;
	return fx;
}

/* -1 <= xi <= 1 dla i = 1...n */
double rastrigin(vector<double> x)
{
	int i, n = x.size();
	double fx = 0.0;

	for ( i = 0; i < n; i++ )
	{
		fx += pow(x[i],2) - cos(18.0*x[i]);
	}

	return fx;
}

double rosenbrock(double x1, double x2)
{
	double fx = 100.0*pow((x2-pow(x1,2)),2) + pow((1.0-x1),2);
	return fx;
}
